package org.ftc.report;

import java.io.File;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import javax.xml.bind.JAXBElement;
import javax.xml.bind.JAXBException;

import org.apache.commons.lang3.StringUtils;
import org.docx4j.XmlUtils;
import org.docx4j.jaxb.Context;
import org.docx4j.model.fields.merge.DataFieldName;
import org.docx4j.model.fields.merge.MailMerger;
import org.docx4j.model.fields.merge.MailMerger.OutputField;
import org.docx4j.model.structure.SectionWrapper;
import org.docx4j.openpackaging.exceptions.Docx4JException;
import org.docx4j.openpackaging.exceptions.InvalidFormatException;
import org.docx4j.openpackaging.packages.WordprocessingMLPackage;
import org.docx4j.openpackaging.parts.Part;
import org.docx4j.openpackaging.parts.WordprocessingML.FooterPart;
import org.docx4j.openpackaging.parts.relationships.Namespaces;
import org.docx4j.openpackaging.parts.relationships.RelationshipsPart;
import org.docx4j.relationships.Relationship;
import org.docx4j.wml.ContentAccessor;
import org.docx4j.wml.FooterReference;
import org.docx4j.wml.Ftr;
import org.docx4j.wml.HdrFtrRef;
import org.docx4j.wml.ObjectFactory;
import org.docx4j.wml.P;
import org.docx4j.wml.R;
import org.docx4j.wml.STBrType;
import org.docx4j.wml.SectPr;
import org.docx4j.wml.Tbl;
import org.docx4j.wml.Text;
import org.docx4j.wml.Tr;

public class Report8 {

	static String[] NUM = { "30", "31", "32", "33", "34", "35", "36", "37", "38", "39", //
			"20", "21", "22", "23", "24", "25", "26", "27", "28", "29", //
			"10", "11", "12", "13", "14", "15", "16", "17", "18", "19", //
			"1", "2", "3", "4", "5", "6", "7", "8", "9", "0" };
	static String[] CHINESE_NUM = { "三十", "三十一", "三十二", "三十三", "三十四", "三十五", "三十六", "三十七", "三十八", "三十九", //
			"二十", "二十一", "二十二", "二十三", "二十四", "二十五", "二十六", "二十七", "二十八", "二十九", //
			"十", "十一", "十二", "十三", "十四", "十五", "十六", "十七", "十八", "十九", //
			"一", "二", "三", "四", "五", "六", "七", "八", "九", "０" };

	public static void main(String[] args) throws Exception {
		report8();
	}

	private static void report8() throws Exception {
		File tmp = new File("D:\\ftc\\1165\\確認單5_2.docx");
		WordprocessingMLPackage template = WordprocessingMLPackage.load(tmp);
		// 變數

		genDocP(template);
		addPageBreak(template);
		genDocP(template);
		addPageBreak(template);
		genDocP(template);
		addPageBreak(template);
		genDocP(template);
		addPageBreak(template);
		// replaceTable("COLUMN1", map2, template);
		System.out.println("===================================");
		RelationshipsPart rp = template.getMainDocumentPart().getRelationshipsPart();
		Relationship rel = rp.getRelationshipByType(Namespaces.FOOTER);
		Part p = rp.getPart(rel);
		List<Object> tables1 = getAllElementFromObject(p, Tbl.class);
		Tbl tempTable = getTemplateTable(tables1, "committee");
		Map<String, String> map3 = new HashMap<>();
		map3.put("committee", "委員一");
		Map<String, String> map4 = new HashMap<>();
		map4.put("committee", "委員二");
		Map<String, String> map5 = new HashMap<>();
		map5.put("committee", "委員三");
		Map<String, String> map6 = new HashMap<>();
		map6.put("committee", "委員四");
		Map<String, String> map7 = new HashMap<>();
		map7.put("committee", "委員x");
		replaceAndAddTable(tempTable, Arrays.asList(map3, map4, map5, map6, map7));

//		 MailMerger.performMerge(template, map7, true);
//		WordprocessingMLPackage output = MailMerger.getConsolidatedResultCrude(template, Arrays.asList(map2, map7),
//				false);
//		Part part1 = template.getMainDocumentPart();
//		List<Object> ps1 = getAllElementFromObject(part1, P.class);
//		List<Object> objs = new ArrayList<>();
//		for (Iterator<Object> iterator = ps1.iterator(); iterator.hasNext();) {
//			Object tbl = iterator.next();
//			List<?> textElements = getAllElementFromObject(tbl, Text.class);
//			for (Object text : textElements) {
//				Text textElement = (Text) text;
//				System.out.println("col value:" + textElement.getValue());
//				if (StringUtils.equals(textElement.getValue(), "r")) {
//					objs.add(tbl);
//				}
//			}
//		}
//		for (Object obj : objs) {
//			template.getMainDocumentPart().getContent().remove(obj);
//		}
//		Relationship relationship = createFooterPart(template);
//        createFooterReference(template, relationship);
        template.save(new java.io.File("D:\\REPORT_8.docx"));
		System.out.println("end");
	}

	private static void replaceTable(String placeholders, Map<String, String> map, WordprocessingMLPackage template)
			throws Docx4JException, JAXBException {
		List<Object> tables = getAllElementFromObject(template.getMainDocumentPart(), Tbl.class);

		// 1. find the table
		Tbl tempTable = getTemplateTable(tables, placeholders);
		List<Object> rows = getAllElementFromObject(tempTable, Tr.class);
		System.out.println("rows size:" + rows.size());
		// first row is header, second row is content
		// this is our template row
		Tr templateRow = (Tr) rows.get(0);
		List<?> textElements = getAllElementFromObject(templateRow, Text.class);
		for (Object object : textElements) {
			Text text = (Text) object;
			System.out.println("textValue:" + text.getValue());
			String value = map.get(text.getValue());
			text.setValue(StringUtils.isBlank(value) ? "" : value);
		}
		templateRow = (Tr) rows.get(1);
		textElements = getAllElementFromObject(templateRow, Text.class);
		for (Object object : textElements) {
			Text text = (Text) object;
			System.out.println("textValue:" + text.getValue());
			String value = map.get(text.getValue());
			text.setValue(StringUtils.isBlank(value) ? "" : value);
		}
	}

	private static void replaceAndAddTable(Tbl tempTable, List<Map<String, String>> textToAdd) throws Docx4JException, JAXBException {
		// 1. find the table
		List<Object> rows = getAllElementFromObject(tempTable, Tr.class);
		System.out.println("rows size:" + rows.size());
		Tr templateRow = (Tr) rows.get(0);
		for (Map<String, String> replacements : textToAdd) {
			// 2 and 3 are done in this method
			addRowToTable(tempTable, templateRow, replacements);
		}
		// 4. remove the template row
		tempTable.getContent().remove(templateRow);
	}

	private static List<Object> getAllElementFromObject(Object obj, Class<?> toSearch) {
		List<Object> result = new ArrayList<Object>();
		if (obj instanceof JAXBElement)
			obj = ((JAXBElement<?>) obj).getValue();

		if (obj.getClass().equals(toSearch))
			result.add(obj);
		else if (obj instanceof ContentAccessor) {
			List<?> children = ((ContentAccessor) obj).getContent();
			for (Object child : children) {
				result.addAll(getAllElementFromObject(child, toSearch));
			}

		}
		return result;
	}

	private static Tbl getTemplateTable(List<Object> tables, String templateKey) throws Docx4JException, JAXBException {
		for (Iterator<Object> iterator = tables.iterator(); iterator.hasNext();) {
			Object tbl = iterator.next();
			List<?> textElements = getAllElementFromObject(tbl, Text.class);
			for (Object text : textElements) {
				Text textElement = (Text) text;
				System.out.println("col value:" + textElement.getValue());
				if (StringUtils.equals(textElement.getValue(), templateKey))
					return (Tbl) tbl;
			}
		}
		return null;
	}

	private static void addRowToTable(Tbl reviewtable, Tr templateRow, Map<String, String> replacements) {
		Tr workingRow = (Tr) XmlUtils.deepCopy(templateRow);
		List<?> textElements = getAllElementFromObject(workingRow, Text.class);
		for (Object object : textElements) {
			Text text = (Text) object;
			System.out.println("textValue:" + text.getValue());
			String replacementValue = (String) replacements.get(text.getValue());
			if (replacementValue != null) {
				System.out.println("replacement:" + replacementValue);
				text.setValue(replacementValue);
			}
		}

		reviewtable.getContent().add(workingRow);
	}

	private static void addPageBreak(WordprocessingMLPackage template) {
		org.docx4j.wml.P p = new org.docx4j.wml.P();
		org.docx4j.wml.R r = new org.docx4j.wml.R();
		org.docx4j.wml.Br br = new org.docx4j.wml.Br();
		br.setType(STBrType.PAGE);
		r.getContent().add(br);
		p.getContent().add(r);
		template.getMainDocumentPart().addObject(p);
	}

	private static String genChineseNum(String original) {
		return StringUtils.replaceEach(original, NUM, CHINESE_NUM);
	}

	private static Relationship createFooterPart(WordprocessingMLPackage template) throws InvalidFormatException {
		FooterPart footerPart = new FooterPart();
		footerPart.setPackage(template);

		footerPart.setJaxbElement(createFooter("Text"));

		return template.getMainDocumentPart().addTargetPart(footerPart);
	}
	
	private static Ftr createFooter(String content) {
		ObjectFactory factory = Context.getWmlObjectFactory();
        Ftr footer = factory.createFtr();
        P paragraph = factory.createP();
        R run = factory.createR();
        Text text = new Text();
        text.setValue(content);
        run.getContent().add(text);
        paragraph.getContent().add(run);
        footer.getContent().add(paragraph);
        return footer;
    }
	
	 private static void createFooterReference(WordprocessingMLPackage template,Relationship relationship) {
		 ObjectFactory factory = Context.getWmlObjectFactory();
	        List<SectionWrapper> sections =
	        		template.getDocumentModel().getSections();
	 
	        SectPr sectionProperties = sections.get(sections.size() - 1).getSectPr();
	        // There is always a section wrapper, but it might not contain a sectPr
	        if (sectionProperties==null ) {
	            sectionProperties = factory.createSectPr();
	            template.getMainDocumentPart().addObject(sectionProperties);
	            sections.get(sections.size() - 1).setSectPr(sectionProperties);
	        }
	 
	        FooterReference footerReference = factory.createFooterReference();
	        footerReference.setId(relationship.getId());
	        footerReference.setType(HdrFtrRef.DEFAULT);
	        sectionProperties.getEGHdrFtrReferences().add(footerReference);
	    }
	 
	 private static void genDocP(WordprocessingMLPackage template) {
		 ObjectFactory factory = Context.getWmlObjectFactory();
		 P paragraph = factory.createP();
	        R run = factory.createR();
	        Text text = new Text();
	        text.setValue("xxxxxxxxx");
	        run.getContent().add(text);
	        paragraph.getContent().add(run);
			template.getMainDocumentPart().getContent().add(paragraph);
		}
	 
	 private static P cloneP(P p, Map<String, String> replacements) {
			P tempP = (P) XmlUtils.deepCopy(p);
			List<?> textElements = getAllElementFromObject(tempP, Text.class);
			for (Object object : textElements) {
				Text text = (Text) object;
				String replacementValue = (String) replacements.get(text.getValue());
				if (replacementValue != null) {
					text.setValue(replacementValue);
				}
			}
			return tempP;
		}
}
